package org.example.cicdi.service.impl.org;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import org.example.cicdi.enums.EnumWhiteColumnAnnotation;
import org.example.cicdi.enums.EnumWhiteTableAnnotation;
import org.example.codegenerate.modelext.WebVo.domian.column.ColumnVoDomain;
import org.example.codegenerate.modelext.WebVo.domian.table.TableVoDomain;
import org.example.codegenerate.modelext.WebVo.domian.table.WebModelVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;

import javax.persistence.OneToMany;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

@Slf4j
//@Service
public class CodeService /*implements ApplicationRunner*/ {
	/*
	 * ManyToOne：org.jeecg.modules.cicdi.jpa.project.child； OneToMany:org.jeecg.modules.cicdi.jpa.project.parent
	 * 2个标签不要嵌套使用，否则死循环
	 */
	private static final String BASE_PACKAGE = "org.jeecg.modules.cicdi.jpa.project.parent";
	
    private static final String RESOURCE_PATTERN = "/**/*.class";
    
    @Autowired
    private List<TableAnnotationService>tableServices;
    
    @Autowired
    private List<FieldAnnotationService>fieldServices;

	//@Override
	public void run(ApplicationArguments args) throws Exception {
		
		//1.读取所有需要生成代码的jpa类
		List<Class<?>>list = queryAllJpa();
		if (CollectionUtils.isEmpty(list)) {
			return;
		}
		
		for (Class<?> cl : list) {
			//2.构件model对象，调用远程服务生成代码
			WebModelVo vo =	createModel(cl);
			
			//3.调用远程服务
			//HttpUtils.sendPost(URL, vo);
			log.info("jpa对象：{}，字符串发送：{}", cl.getName(), new Gson().toJson(vo));
		}
	}
	
	/*
	 * 获取指定路径的所有jpa类
	 */
	private List<Class<?>> queryAllJpa(){
		List<Class<?>>list = new ArrayList<>();
        try {
        	//spring工具类，可以获取指定路径下的全部类
            ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        	
            String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(BASE_PACKAGE) + RESOURCE_PATTERN;
            Resource[] resources = resourcePatternResolver.getResources(pattern);
            
            //MetadataReader 的工厂类
            MetadataReaderFactory refractory = new CachingMetadataReaderFactory(resourcePatternResolver);
            for (Resource resource : resources) {
                //用于读取类信息
                MetadataReader reader = refractory.getMetadataReader(resource);
                //扫描到的class
                String classname = reader.getClassMetadata().getClassName();
                
                Class<?> cl = Class.forName(classname);
                if (cl.getAnnotation(org.hibernate.annotations.Table.class) != null) {
                	list.add(cl);
                }
            }
        } catch (Exception exception) {
        }
		
		return list;
	}

	/*
	 * 构件代码生成的model对象
	 */
	private WebModelVo createModel(Class<?> cl) throws Exception{
		WebModelVo model = new WebModelVo();
		
		//1.处理类注解
		handleTableAnnotations(cl, model);
		
		//2.处理字段注解
		List<ColumnVoDomain> columnVoDomainList = handleFieldAnnotations(cl, model);
		model.getTableVoDomain().setColumnVoDomainList(columnVoDomainList);
		
		return model;
	}



	private void handleTableAnnotations(Class<?> cl, WebModelVo model) {
		if (CollectionUtils.isEmpty(tableServices)) {
			return;
		}
		
		for (TableAnnotationService service : tableServices) {
			if (EnumWhiteTableAnnotation.getByCode(service.getCode()) != null) {
				service.handleTableVo(cl, model);
			}
		}
		
		log.info("类：{}，表数据封装：{}", cl.getName(), JSONObject.toJSON(model));
	}
	
	private List<ColumnVoDomain> handleFieldAnnotations(Class<?> cl, WebModelVo model) throws Exception{
		Field[]fields = cl.getDeclaredFields();
		if (fields == null || fields.length == 0) {
			throw new Exception("对象可用字段为空");
		}
		
		List<ColumnVoDomain>list = new ArrayList<>();
		for (Field field : fields) {
			field.setAccessible(true);
			
//			//递归处理manyToOne
//			if (field.getAnnotation(ManyToOne.class) != null) {
//				Class<?>fClass = field.getType();
//				WebModelVo sonModel = createModel(fClass);
//				TableVoDomain sonTable = sonModel.getTableVoDomain();
//				model.getTableVoDomain().getParentTabeleVoDomain().add(sonTable);
//			}
			
			//递归处理oneToMany
			if (field.getAnnotation(OneToMany.class) != null) {
				if (field.getType().equals(List.class)) {
					Type type = field.getGenericType();
	                if (type instanceof ParameterizedType) {
	                    ParameterizedType pt = (ParameterizedType) type;
	                    // 获取泛型里的class类型对象
	                    Class<?> fClass = (Class<?>)pt.getActualTypeArguments()[0];
	                    WebModelVo sonModel = createModel(fClass);
	    				TableVoDomain sonTable = sonModel.getTableVoDomain();
	    				model.getTableVoDomain().getSonTabeleVoDomain().add(sonTable);
	                }
				}
			}
			
			ColumnVoDomain columnVoDomain = new ColumnVoDomain();
			if (CollectionUtils.isEmpty(fieldServices)) {
				break;
			}
			
			for (FieldAnnotationService service : fieldServices) {
				if (EnumWhiteColumnAnnotation.getByCode(service.getCode()) != null) {
					service.handleFieldVo(field, columnVoDomain);
				}
			}
			
			if (columnVoDomain.getDbVo() != null && StringUtils.isNotBlank(columnVoDomain.getDbVo().getDbFieldName())) {
				list.add(columnVoDomain);
			}
		}
		return list;
	}

}
